<template>
  <header>
    <div class="location">
      <span>{{ location }}</span>
    </div>
    <div class="input">
      <input type="text" placeholder="请搜索你所在的城市" v-model="searchCity" @input="handleInput(searchCity)" />
    </div>
    <div class="reset">
      <button @click="handleReset('武汉')">复位地图</button>
    </div>
    <el-select v-model="tool" placeholder="请选择工具" @change="handleToolChange">
      <el-option label="线" value="line"></el-option>
      <el-option label="圆" value="circle"></el-option>
      <el-option label="多边形" value="polygon"></el-option>
      <el-option label="停止画图" value="stop"></el-option>
    </el-select>
  </header>
  <table>
    <tr>
      <td>城市</td>
      <td>{{ weatherData.city }}</td>
    </tr>
    <tr>
      <td>天气</td>
      <td>{{ weatherData.weather }}</td>
    </tr>
    <tr>
      <td>温度</td>
      <td>{{ weatherData.temperature }}°C</td>
    </tr>
    <tr>
      <td>风向</td>
      <td>{{ weatherData.winddirection }}</td>
    </tr>
    <tr>
      <td>风力</td>
      <td>{{ weatherData.windpower }}</td>
    </tr>
  </table>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { Feature, Map, View } from 'ol';
import GeoJSON from 'ol/format/GeoJSON.js';
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
import TileLayer from 'ol/layer/Tile.js';
import XYZ from 'ol/source/XYZ.js';
import Style from 'ol/style/Style.js';
import Stroke from 'ol/style/Stroke';
import Fill from 'ol/style/Fill.js';
import axios from 'axios';
import Overlay from 'ol/Overlay.js';
import Draw from 'ol/interaction/Draw';
import { Point } from 'ol/geom';
import Icon from 'ol/style/Icon';
import busIcon from './assets/img/bus.png';
import { Cluster } from 'ol/source';
import Circle from 'ol/style/Circle';
import Text from 'ol/style/Text';

const location = ref('武汉');
const searchCity = ref('');
const weatherData = ref({});
const tool = ref('');
let foundCity = false;

let map, view, tileLayer, vectorLayer, vectorSource, iconSource, iconLayer, iconClusterSource, draw;
let popup;

// 设置选中样式
const selectStyle = new Style({
  stroke: new Stroke({
    color: 'red',
    width: 5,
  }),
  fill: new Fill({
    color: 'rgba(125, 124, 120, 0.5)',
  }),
});

const handleInput = async value => {
  if (value.length < 2) return;

  const source = map.getLayers().item(1).getSource();
  const allFeatures = source.getFeatures();

  allFeatures.forEach(item => {
    item.setStyle(null);
    if (item.values_.name.includes(value)) {
      location.value = item.values_.name.split('市')[0];
      const coordinate = item.values_.center;
      view.animate({
        center: coordinate,
        duration: 2000,
        zoom: 8,
      });
      item.setStyle(selectStyle);
      foundCity = true;
    }
  });

  if (foundCity) {
    try {
      const res = await axios.get(
        `https://restapi.amap.com/v3/weather/weatherInfo?city=${location.value}&key=6f5e88ec2764db25e3e75a718effe617&extensions=base`
      );
      weatherData.value = res.data.lives[0];
    } catch (error) {
      console.error(error);
    }
  }

  searchCity.value = '';
};

const handleReset = city => {
  handleInput(city);
  view.animate({
    zoom: 5,
    duration: 3000,
  });
};

const handleToolChange = value => {
  map.removeOverlay(popup);
  map.removeInteraction(draw);
  draw = null;
  if (value === 'stop') {
    map.removeInteraction(draw);
    map.addOverlay(popup);
    draw = null;
    tool.value = '';
    return;
  }
  if (value === 'line') {
    draw = new Draw({
      source: vectorSource,
      type: 'LineString',
      style: new Style({
        stroke: new Stroke({
          color: 'red',
          width: 3,
        }),
      }),
    });
    map.addInteraction(draw);
  }
  if (value === 'circle') {
    draw = new Draw({
      source: vectorSource,
      type: 'Circle',
      style: new Style({
        stroke: new Stroke({
          color: 'red',
          width: 3,
        }),
        fill: new Fill({
          color: 'rgba(255, 0, 0, 0.2)',
        }),
      }),
    });
    map.addInteraction(draw);
  }
  if (value === 'polygon') {
    draw = new Draw({
      source: vectorSource,
      type: 'Polygon',
      style: new Style({
        stroke: new Stroke({
          color: 'red',
          width: 3,
        }),
        fill: new Fill({
          color: 'rgba(255, 0, 0, 0.2)',
        }),
      }),
    });
    map.addInteraction(draw);
  }
};

onMounted(async () => {
  const center = [114.298572, 30.584355];
  view = new View({
    projection: 'EPSG:4326',
    center: center,
    zoom: 5,
  });

  try {
    const response = await axios.get('https://geo.datav.aliyun.com/areas_v3/bound/100000_full_city.json');
    const geojsonObject = response.data;

    tileLayer = new TileLayer({
      source: new XYZ({
        url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
        wrapX: false,
      }),
    });

    vectorSource = new VectorSource({
      features: new GeoJSON().readFeatures(geojsonObject),
    });

    vectorLayer = new VectorLayer({
      source: vectorSource,
    });

    iconSource = new VectorSource({
      features: [],
    });

    iconClusterSource = new Cluster({
      distance: 10,
      source: iconSource,
    });

    iconLayer = new VectorLayer({
      source: iconClusterSource,
      style: feature => {
        const features = feature.get('features') || []; // 确保不会是 undefined
        const size = features.length;
        let style;

        if (size === 1) {
          // 单个点的样式
          style = new Style({
            image: new Icon({
              src: busIcon,
              scale: 0.7,
            }),
          });
        } else {
          // 聚合点的样式
          style = new Style({
            image: new Circle({
              radius: 10 + size, // 以聚合数量调整半径
              fill: new Fill({ color: 'rgba(255, 255, 255, 0.6)' }),
              stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.6)', width: 2 }),
            }),
            text: new Text({
              text: size.toString(),
              fill: new Fill({ color: '#000' }),
              stroke: new Stroke({ color: '#fff', width: 2 }),
              font: 'bold 14px Arial',
            }),
          });
        }

        return style;
      },
    });

    map = new Map({
      target: 'map',
      view: view,
      layers: [tileLayer, vectorLayer, iconLayer],
    });

    popup = new Overlay({
      element: document.getElementById('popup'),
    });
    map.addOverlay(popup);

    let curFeature = null;

    map.on('click', e => {
      if (!tool.value) {
        const coordinate = e.coordinate;
        const clickedFeature = vectorSource.getFeaturesAtCoordinate(coordinate)[0];

        // 先重置所有要素的样式
        vectorSource.getFeatures().forEach(item => {
          item.setStyle(null);
        });

        // 如果点击到了要素，设置其样式
        if (clickedFeature) {
          curFeature = clickedFeature; // 更新当前要素
          curFeature.setStyle(selectStyle); // 为选中的要素添加样式

          const name = curFeature.get('name');
          const center = curFeature.get('center');
          popup.setPosition(center);
          const popupElement = document.getElementById('popup');
          popupElement.innerHTML = `<p>城市:${name}</p><p>经度:${center[0]}</p><p>纬度:${center[1]}</p>`;
        } else {
          curFeature = null;
        }
      }
    });

    map.on('click', function (e) {
      const coordinate = e.coordinate;
      const busFeature = new Feature({
        geometry: new Point(coordinate),
      });

      iconSource.addFeature(busFeature);
    });

    map.on('moveend', () => {
      const currentZoom = view.getZoom();
      // console.log(currentZoom);

      if (curFeature) {
        if (currentZoom < 10) {
          // 重新为当前要素添加样式
          curFeature.setStyle(selectStyle);
          vectorLayer.setVisible(true);
          iconLayer.setVisible(false);
        } else {
          // 如果缩放级别大于等于10，重置样式
          curFeature.setStyle(null);
          vectorLayer.setVisible(true);
          iconLayer.setVisible(true);
        }
      }
    });

    view.animate({
      duration: 2000,
      zoom: 8,
    });

    handleInput('武汉'); // 默认选择武汉
  } catch (error) {
    console.error(error);
  }
});
</script>

<style lang="scss" scoped>
@import 'ol/ol.css';

header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 50px;
  background-color: #4164fc;
  display: flex;
  align-items: center;
  color: #fff;
  z-index: 999;
  .location {
    margin-left: 20px;
    margin-right: 40px;
  }
  .input {
    margin-right: 20px;
    input {
      width: 200px;
      height: 30px;
      padding: 0 10px;
      border: none;
      border-radius: 3px;
      outline: none;
    }
  }
  .reset {
    button {
      width: 80px;
      height: 30px;
      background-color: #fff;
      border: none;
      border-radius: 3px;
      cursor: pointer;
    }
  }
  .el-select {
    margin-left: 20px;
    width: 130px;
    height: 30px;
    border: none;
    border-radius: 3px;
  }
}
table {
  position: fixed;
  right: 20px;
  top: 60px;
  background-color: #53acbe;
  color: #fff;
  text-align: center;
  width: 200px;
  line-height: 30px;
  border-radius: 15px;
  border-collapse: collapse;
  z-index: 998;
  tr {
    vertical-align: middle;
  }
  td {
    border: 1px solid rgba(238, 238, 238, 0.473);
  }
}
</style>
